import trigger from "../../effect/trigger.js";
import { TriggerOpTypes, hasChanged } from "../../utils.js";

/**
 * 拦截 set 操作
 * @param {*} target
 * @param {*} key
 * @param {*} value
 */
export default function (target, key, value) {
  // 根据是否存在属性判断是新增还是修改
  const type = target.hasOwnProperty(key)
    ? TriggerOpTypes.SET
    : TriggerOpTypes.ADD;

  // 缓存旧值
  const oldValue = target[key];
  // 缓存旧数组长度
  const oldLen = Array.isArray(target) ? target.length : undefined;

  const result = Reflect.set(target, key, value);
  //   若新值与旧值不相同，则派发更新
  if (hasChanged(oldValue, value)) {
    trigger(target, type, key);

    // 判断数组长度是否发生改变
    if (Array.isArray(target) && oldLen !== target.length) {
      // 判断是否为隐式改变数组长度
      if (key !== "length") {
        // 隐式改变数组长度
        trigger(target, TriggerOpTypes.SET, "length");
      } else {
        // 显示改变数组长度
        // 当新数组长度小于旧数组长度时，触发删除操作
        for (let i = target.length; i < oldLen; i++) {
          trigger(target, TriggerOpTypes.DELETE, i.toString());
        }
      }
    }
  }

  return result;
}
